// Tracker.h: interface for the Tracker class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_TRACKER_H__DF406AB0_8C1C_11D1_93E4_006097737B41__INCLUDED_)
#define AFX_TRACKER_H__DF406AB0_8C1C_11D1_93E4_006097737B41__INCLUDED_

//#include "function.h"
//#include "wrapperFunctions.h"

  // container for MRSA

  struct Sol
  {
    double funcVal;
    vector<double> coord; // hold coordinates of solution

    Sol(double fV, double *coordinate, int nCoor) : funcVal(fV)
    { 
      for (int i = 1; i <= nCoor; i++)
        coord.push_back(coordinate[i]);
    }
  };

class Tracker  
{
private:
	int		N;
	double	valueStored, *solutionStored;
  double	valueStored2, *solutionStored2; // used for testing MRSA



  vector<Sol> solContainer;

public:
  vector<int> whichNmc;

	Tracker()			{	valueStored = 1e16; valueStored2 = 1e16;}
	virtual ~Tracker()	{	deleteA(solutionStored); deleteA(solutionStored2);	}

	void Size(int i_N)	{	N = i_N;	newA(solutionStored,N);	newA(solutionStored2,N);}

	void Input(double x, double *y)
	{
		if(x<valueStored) 
		{
			valueStored = x;
			CopyA(solutionStored,y,N);  // copy from y -> solutionStored
    }

    // do the same for second solution (only used with MRSA)
		if(x<valueStored2) 
		{
			valueStored2 = x;
			CopyA(solutionStored2,y,N); 
		}
	}
  
  void Input(double x, vector<double> &y)
	{
		if(x<valueStored) 
		{
			valueStored = x;

      for (unsigned int i = 0; i < y.size(); i++)
      {
        solutionStored[i+1] = y[i];
      }
		}

    // do the same for second solution (only used with MRSA)
		if(x<valueStored2) 
		{
			valueStored2 = x;

      for (unsigned int i = 0; i < y.size(); i++)
      {
        solutionStored2[i+1] = y[i];
      }
		}
	}

	double BestChiSq(void) {return valueStored;}


  // return the stored X and Y in x and y
	void Best(double &x, double *y)
  {
		x = valueStored;

    CopyA(y,solutionStored,N);  // copy from solutionStored -> y
	}

  void BestInCont(double &x, double *y)
  {
    int bestPos = 0;
    double lBest = solContainer[0].funcVal;
    for(unsigned int i = 1; i < solContainer.size(); i++)
    {
      if(solContainer[i].funcVal < lBest)
      {
        lBest = solContainer[i].funcVal;
        bestPos = i;
      }
    }

    x = lBest;

    for(int j = 0; j < N; j++)
    {
      y[j+1] = solContainer[bestPos].coord[j];
    }
  }

  void getCoordFromCont(int whichOne, double **x[])
  {
    double *y[14];
    for(int i = 0; i<N; i++)
    {
      y[i] = &(solContainer[whichOne].coord[i]);
    }
    x[whichOne] = y;
  }


  vector<Sol>& getCoordFromCont()
  {
    return solContainer;
  }


  void printSolution(ofstream &out)
  {
    for (int i = 1; i <= N; i++)
    {
      out << solutionStored[i] << "  ";
    }
    out << endl;
  }

  void Best(double &x)
  {
		x = valueStored;
	}

  double getBestValue()
  {
    return valueStored;
  }
  

	void ResetWith(double x, double *y)
	{
			valueStored = x;
			CopyA(solutionStored,y,N);	
	}

  void ResetCont()
  {
    solContainer.clear();
    valueStored2 = 1e16;
    whichNmc.clear();
  }

  // Method used only with MRSA
  void resetSecondSol(int whichSample, double NMin)
  {
	  // Add solution to MRSA container

    if(fmod((double) whichSample, (double) NMin) == 0.0)
    {
      whichNmc.push_back(whichSample);
      solContainer.push_back(Sol(valueStored2, solutionStored2, N));
    }

    // reset 2nd solution
	  valueStored2 = 1e16;
  }

  void resetSecondSol()
  {
	  // Add solution to MRSA container
    solContainer.push_back(Sol(valueStored2, solutionStored2, N));

    // reset 2nd solution
	  valueStored2 = 1e16;
  }

  // for testing MRSA algorithm

  void printSolContainer(string& filename)
  {
    cout << "coord1 = " << solContainer[0].coord[1] << endl;

    for (unsigned int i = 0; i < solContainer.size(); i++)
    {
      cout << "val" << i << " = " << solContainer[i].funcVal << endl;
    }
    
  }

};

#endif // !defined(AFX_TRACKER_H__DF406AB0_8C1C_11D1_93E4_006097737B41__INCLUDED_)
